package com.yfqy.app.modules.order.director;

import com.yfqy.app.domain.entity.ProductSku;
import com.yfqy.app.domain.entity.ProductSpu;
import com.yfqy.app.enums.OrderType;
import com.yfqy.app.modules.order.dto.OrderAmountDTO;
import com.yfqy.app.modules.order.dto.OrderCreateRequest;
import com.yfqy.app.modules.order.dto.OrderItemRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

/**
 * 普通订单
 */
@Service
@Slf4j
public class NormalOrderCreateBuilderDirector extends AbstractOrderCreateBuilderDirector {


    @Override
    public OrderType getOrderType() {
        return OrderType.NORMAL;
    }

    @Override
    public void validRequiredParam(OrderCreateRequest request) {
        validateParams(request);
        validateProducts(request);
    }


    @Override
    public OrderAmountDTO calculateAmount(OrderCreateRequest request) {
        // 1. 重新计算商品总金额
        BigDecimal calculatedTotal = calculateTotalAmount(request.getItems());

        OrderAmountDTO amountDTO = request.getOrderAmountDTO();
        // 2. 校验并修正总金额
        if (amountDTO.getTotalAmount() == null || !amountDTO.getTotalAmount().equals(calculatedTotal)) {
            log.warn("前端总金额计算错误，已修正。前端值: {}, 计算值: {}", amountDTO.getTotalAmount(), calculatedTotal);
            amountDTO.setTotalAmount(calculatedTotal);
        }

        // 3. 重新计算商品实付金额（总金额 - 优惠 - 积分抵扣）
        BigDecimal paymentAmount = calculatedTotal;

        // 4. 没有促销优惠
        amountDTO.setDiscountAmount(BigDecimal.ZERO);

        // 5. 如果有积分抵扣
        if (request.isUsePoints()) {
            applyPointsDeduction(amountDTO, paymentAmount);
        } else {
            resetPointsDeduction(amountDTO);
        }

        // 6. 设置最终商品实付金额
        paymentAmount = paymentAmount.subtract(amountDTO.getPointAmount()).max(BigDecimal.ZERO);
        amountDTO.setPaymentAmount(paymentAmount);

        // 7. 最终商品实付金额是否免运费
        calculateFreightAmount(amountDTO);

        // 8. 更新前端的amount对象
        request.setOrderAmountDTO(amountDTO);
        return amountDTO;
    }

    @Override
    public void validateProducts(OrderCreateRequest request) {
        log.info("执行普通订单的商品、价格、库存校验");
        List<OrderItemRequest> items = request.getItems();
        // 一次性获取所有需要的ID
        List<Long> spuIds = items.stream().map(OrderItemRequest::getSpuId).distinct().toList();
        List<Long> skuIds = items.stream().map(OrderItemRequest::getSkuId).distinct().toList();

        // 批量查询商品信息
        Map<Long, ProductSpu> spuMap = batchGetAndValidateSpus(spuIds);
        Map<Long, ProductSku> skuMap = batchGetAndValidateSkus(skuIds, spuMap);

        // 校验价格
        validatePrice(items, spuMap, skuMap);
        // 校验库存
        validateStock(items, spuMap, skuMap);
        // 填充sku信息
        completeSku(items, spuMap, skuMap);
    }

    @Override
    public void specificValidate(OrderCreateRequest request) {
        // nothing to do
    }

}
